<template>
  <div>
    <h2>父组件</h2>
    <div>
      <h3>父组件中的数据：</h3>
      <p v-if="message">收到的消息: {{ message.text }}</p>
      <p v-if="message">时间戳: {{ message.timestamp }}</p>
      <p v-if="globalMessage">全局消息: {{ globalMessage }}</p>
      
      <button @click="sendToChild">发送消息到子组件</button>
      <button @click="broadcastMessage">广播全局消息</button>
    </div>
    <Child />
    <Child2 />
  </div>
</template>

<script lang="ts" setup>
/**
 * Mitt 事件总线详解 - 父组件部分
 * 
 * 1. 创建 Mitt 实例：
 *    通常在一个单独的文件中创建并导出 mitt 实例，
 *    以便在整个应用中共享同一个事件总线。
 * 
 * 2. 事件监听与发送：
 *    - on: 监听事件
 *    - emit: 发送事件
 *    - off: 移除事件监听
 * 
 * 3. 使用场景：
 *    3.1 非父子组件通信：如兄弟组件、远亲组件之间的数据传递
 *    3.2 跨多层级组件通信：避免多层 props 传递或事件冒泡
 *    3.3 全局事件通知：如全局消息提醒、主题切换等
 *    3.4 组件与非组件模块的通信：如与工具函数的交互
 * 
 * 4. 与其他通信方式的对比：
 *    - Props/Events: 适用于父子组件通信
 *    - Provide/Inject: 适用于深层嵌套组件
 *    - Vuex/Pinia: 适用于复杂的状态管理
 *    - Mitt: 适用于简单的跨组件通信，尤其是非嵌套关系的组件
 */

import { ref, onMounted, onUnmounted } from 'vue';
import Child from './child.vue';
import Child2 from './child2.vue';
// 引入全局 mitt 实例
import emitter from '@/utils/eventBus';

// 用于存储接收到的消息
const message = ref(null);
const globalMessage = ref('');

// 发送消息到子组件
function sendToChild() {
  emitter.emit('parent-message', '这是来自父组件的消息');
}

// 广播全局消息
function broadcastMessage() {
  emitter.emit('global-broadcast', '父组件广播的全局消息');
}

// 在组件挂载时设置事件监听
onMounted(() => {
  // 监听子组件发送的消息
  emitter.on('child-message', (data) => {
    message.value = data;
    console.log('父组件收到子组件消息:', data);
  });
  
  // 监听全局消息
  emitter.on('global-message', (data) => {
    globalMessage.value = data;
    console.log('收到全局消息:', data);
  });
});

// 在组件卸载时移除事件监听
onUnmounted(() => {
  // 移除特定事件监听
  emitter.off('child-message');
  emitter.off('global-message');
  
  // 也可以使用通配符移除多个事件
  // emitter.off('global-*');
});

/**
 * 5. Mitt 的高级用法：
 * 
 * 5.1 使用通配符监听多个事件：
 *     emitter.on('user-*', callback) // 监听所有以 'user-' 开头的事件
 * 
 * 5.2 一次性监听事件：
 *     const handler = (e) => {
 *       console.log(e);
 *       emitter.off('event', handler); // 处理后立即移除
 *     };
 *     emitter.on('event', handler);
 * 
 * 5.3 TypeScript 类型定义：
 *     // 在创建 mitt 实例时定义事件类型
 *     type Events = {
 *       'message': { text: string, timestamp: string };
 *       'increment': number;
 *     };
 *     const emitter = mitt<Events>();
 * 
 * 6. 最佳实践：
 *    6.1 事件命名使用命名空间：如 'user:login', 'cart:update'
 *    6.2 在组件卸载时清理事件监听，避免内存泄漏
 *    6.3 不要过度依赖全局事件总线，对于复杂状态管理考虑使用 Pinia
 *    6.4 使用 TypeScript 类型定义增强类型安全
 */
</script>

<style scoped>
/* 父组件样式 */
div {
  background: linear-gradient(to right, #8e2de2, #4a00e0);
  border-radius: 15px;
  padding: 30px;
  color: white;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
  max-width: 800px;
  margin: 20px auto;
}

h2 {
  font-size: 28px;
  margin-bottom: 25px;
  text-align: center;
  font-weight: 600;
  letter-spacing: 1.5px;
  text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
  position: relative;
  padding-bottom: 15px;
}

h2::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100px;
  height: 3px;
  background-color: rgba(255, 255, 255, 0.5);
  border-radius: 3px;
}

p {
  font-size: 18px;
  margin: 10px 0;
  padding: 10px;
  background-color: rgba(255, 255, 255, 0.1);
  border-radius: 8px;
}

button {
  background-color: white;
  color: #8e2de2;
  border: none;
  padding: 10px 15px;
  margin-right: 10px;
  margin-top: 15px;
  border-radius: 8px;
  font-weight: bold;
  cursor: pointer;
  transition: all 0.2s;
  box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}

button:hover {
  background-color: #f0f0f0;
  color: #4a00e0;
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
</style>